package com.lapelife.backend.datasource;

import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lapelife.backend.common.RedisContains;
import com.lapelife.backend.mapper.PostMapper;
import com.lapelife.backend.model.domain.Post;
import com.lapelife.backend.service.PostService;
import com.lapelife.backend.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

public class CSDNDataSourceImpl extends DataSource<Post> {

    private RedisUtil redisUtil;

    private PostService postService;

    private PostMapper postMapper;

    private ChromeOptions options;

    public void setPostMapper(PostMapper postMapper) {
        this.postMapper = postMapper;
    }

    public void setPostService(PostService postService) {
        this.postService = postService;
    }

    public void setRedisUtil(RedisUtil redisUtil) {
        this.redisUtil = redisUtil;
    }

    public CSDNDataSourceImpl(RedisUtil redisUtil, PostService postService, PostMapper postMapper) {
        this.redisUtil = redisUtil;
        this.postService = postService;
        this.postMapper = postMapper;

        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.setPageLoadStrategy(PageLoadStrategy.EAGER);
        // chromeOptions.addArguments("--headless");
        this.options = chromeOptions;
    }


    @Override
    public Page<Post> search(String key) {
        return null;
    }

    @Override
    public List<Post> findPost(int count, String... key) {
        String url = "https://www.csdn.net/";
        count--;
        Boolean b = false;
        List<Post> postList = new ArrayList<>();

        ChromeDriver driver = new ChromeDriver(options);
        driver.get(url);
        try {
            List<String> array = Arrays.asList(key);
            //显式等待， 针对某个元素等待
            WebDriverWait wait = new WebDriverWait(driver, 10, 1);
            WebElement searchElement = wait.until(v -> v.findElement(By.cssSelector("#toolbar-search-input")));
            WebElement btnElement = wait.until(v -> v.findElement(By.cssSelector("#toolbar-search-button")));
            String searchPage = driver.getWindowHandle();
            Set<String> oldHandles = new HashSet<>();
            Set<String> handles = new HashSet<>();
            for (String s : array) {
                System.out.println("driver = " + driver.getTitle());
                searchElement.clear();
                searchElement.sendKeys(s);
                btnElement.click();
                Thread.sleep(50);
                handles.addAll(driver.getWindowHandles());
                for (String v : handles) {
                    if (!searchPage.equals(v) && !oldHandles.contains(v)) {
                        oldHandles.add(v);
                        driver.switchTo().window(v);
                    }
                }

                int size = 0;
                int total = 0;
                int lock = 3;
                int tmp = count;
                Set<WebElement> setList = new LinkedHashSet<>();
                while (tmp >= 0 && lock > 0) {
                    wait.until(v -> v.findElement(By.cssSelector(".so-items-normal")));

                    List<WebElement> elements = driver.findElements(By.cssSelector(".so-items-normal"));
                    setList.addAll(elements);
                    total = elements.size();

                    System.out.println("total = " + total);
                    System.out.println("size = " + (total - size));

                    // 数据处理
                    List<Post> tempPostList = handleData(size, total, tmp, setList);
                    tmp -= tempPostList.size();
                    lock = tempPostList.size() == 0 ? lock - 1 : 3;

                    size = elements.size();

                    // 加载数据
                    if (tmp >= 0) {
                        loadPage(driver);
                    }
                    postList.addAll(tempPostList);
                }
                driver.switchTo().window(searchPage);
            }
            b = postDetail(postList);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            driver.quit();
        }
        return b?postList:new ArrayList<>();
    }

    private void loadPage(ChromeDriver driver) throws InterruptedException {
        try {
            ((JavascriptExecutor) driver).executeScript("document.getElementsByClassName('passport-login-container')[0].style.display = 'none'");
        } catch (Exception e) {
            System.out.println("没有弹框");
        }
        // 点击加载按钮
        try {
            driver.findElement(By.cssSelector(".so-load-data")).click();
            Thread.sleep(1000);
        } catch (Exception e) {
            System.out.println("没有加载按钮");
        }
        //将页面滚动条拖到底部
        ((JavascriptExecutor) driver).executeScript("window.scrollTo(0,100000000);");
        Thread.sleep(3000);
    }

    private List<Post> handleData(int current, int size, int count, Set<WebElement> elements) throws ParseException {
        int tmp = count;
        List<Post> postList = new ArrayList<>();
        System.out.println("elements = " + elements.size());
        Object[] array = elements.toArray();
        for (int i = current; i < size; i++) {
            try {
                if (tmp < 0) {
                    break;
                }
                WebElement element = (WebElement) array[i];

                String text = element.getText();
                String[] content = text.split("\n");
                String href = element.findElement(By.cssSelector("a")).getAttribute("href");
                if (!href.contains("/article/details/")) {
                    continue;
                }
                // int len = content.length;
                System.out.println("----------------------");

                href = href.split("\\?")[0];
                System.out.println("href = " + href);
                String title = content[0];
                System.out.println("标题：" + title);
                // String str = content[1];
                // System.out.println("内容：" + str);
                // Integer read = patternLook(content[2]);
                // System.out.println("浏览量：" + read);
                // if (content[len - 1].length() < 10) {
                //     len--;
                // }
                // String user = content[len - 1].substring(0, content[len - 1].length() - 10);
                // String time = content[len - 1].substring(user.length());
                // System.out.println("作者：" + user);
                // System.out.println("创建时间：" + time);

                Post post = new Post();
                post.setFromUrl(href);
                post.setTitle(title);
                // post.setContent(str);
                // post.setTags("");
                // post.setLooks(read);
                // post.setCollects(0);
                // post.setAuthor(user);
                // Date dateTime = new SimpleDateFormat("yyyy-MM-dd").parse(time);
                // post.setCreateTime(dateTime);
                // post.setUpdateBy(user);
                // post.setUpdateTime(dateTime);
                // post.setRemark("从CSDN爬取的数据");
                postList.add(post);
            } catch (Exception e) {
                System.out.println("获取文章简要信息失败！！");
            }finally {
                tmp = tmp - 1;
            }
        }
        System.out.println("--------------");
        return postList;
    }

    private Integer patternLook(String read) {
        String number = read.split("[万+]")[0];
        Double look = 0.0;
        if (read.contains("万+")) {
            look = Convert.convert(Double.class, number);
            look = Math.ceil(look * 10000);
        }
        Integer result = Convert.convert(Integer.class, look + (read.contains(".") ? (Math.random() * 1000) : (Math.random() * 10000)));
        System.out.println("浏览量：" + result);
        return result;
    }

    private Boolean postDetail(List<Post> list) throws ParseException {
        Object o = redisUtil.get(RedisContains.POST_DETAIL_ADD_TO_DB);
        if (o != null && o.toString().equals("1")) {
            return false;
        }
        Thread thread = new Thread(() -> {
            Set<String> urlList = new HashSet<>();
            list.forEach(v -> urlList.add(v.getFromUrl()));
            // 从数据库获取相同url的文章
            List<String> dataUrlList = postMapper.selectFromUrlByFromUrlIn(urlList);

            // 比较爬取的文章的url与数据库的文章url
            List<Post> postList = list.stream().filter(v -> !dataUrlList.contains(v.getFromUrl())).collect(Collectors.toList());

            if (postList.size() == 0) {
                return;
            }
            Object obj = redisUtil.get(RedisContains.POST_DETAIL_ADD_TO_DB);
            if (obj == null || obj.toString().equals("0")) {
                redisUtil.set(RedisContains.POST_DETAIL_ADD_TO_DB, "1",60*60);
                try {
                    ChromeOptions options = new ChromeOptions();
                    options.setPageLoadStrategy(PageLoadStrategy.EAGER);
                    ChromeDriver driver = new ChromeDriver(options);
                    SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd");
                    WebDriverWait wait = new WebDriverWait(driver, 10, 1);
                    for (Post post : postList) {
                        try {
                            driver.get(post.getFromUrl());

                            WebElement bar = wait.until(v -> driver.findElement(By.cssSelector(".article-info-box")));
                            WebElement detail = wait.until(v -> driver.findElement(By.cssSelector("#content_views")));

                            String[] split = bar.getText().split("\n");
                            int i = split[0].equals("置顶") ? 1 : 0;

                            String author = split[i];
                            Date time = null;
                            try {
                                time = timeFormat.parse(split[1 + i].substring(2, 21));
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                            int looks = Convert.convert(Integer.class, split[2 + i]);
                            // int collects = Convert.convert(Integer.class, split[3 + i].substring(3));
                            String tags = "";
                            if ((split[split.length - 1].equals("版权") && 6 + i == split.length) || (!split[split.length - 1].equals("版权") && 5 + i == split.length)) {
                                tags = split[4 + i].substring(split[4 + i].indexOf("文章标签： ") + 6);
                            }
                            String content = detail.getAttribute("innerHTML");
                            if (content == null) {
                                throw new Exception();
                            }

                            // System.out.println("author = " + author);
                            // System.out.println("time = " + time);
                            // System.out.println("looks = " + looks);
                            // System.out.println("collects = " + collects);
                            // System.out.println("tags = " + tags);
                            // System.out.println("content = " + content);

                            post.setAuthor(author);
                            post.setCreateTime(time);
                            post.setUpdateTime(time);
                            post.setLooks(looks);
                            // post.setCollects(collects);
                            post.setCollects(0);
                            post.setTags(tags);
                            post.setContent(content);

                            post.setCreateBy("Admin");
                            post.setRemark("从CSDN爬取的数据");

                            System.out.println(post.getTitle() + " = " + post.getFromUrl());
                        } catch (Exception e) {
                            System.out.println("post = " + post.getFromUrl() + "，查询详情失败");
                            e.printStackTrace();
                        }
                    }
                    driver.quit();
                    postService.saveBatch(postList);
                    System.out.println("处理完成！");
                } catch (Exception e) {
                    e.printStackTrace();
                }finally {
                    redisUtil.set(RedisContains.POST_DETAIL_ADD_TO_DB, "0",60*60);
                }
            }
        });
        thread.start();
        return true;
    }

    public static void main(String[] args) throws ParseException {
        // String url = "https://blog.csdn.net/allway2/article/details/112058450?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522168336303216800180667506%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=168336303216800180667506&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-2-112058450-null-null.142^v86^control,239^v2^insert_chatgpt&utm_term=java%E5%B0%86%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%BD%AC%E4%B8%BA%E6%97%A5%E6%9C%9F";
        // String s = url.split("\\?")[0];


        // String read = "8.8万+";
        // String number = read.split("[万+]")[0];
        //
        // Double look = 0.0;
        // if (read.contains("万+")) {
        //     look = Convert.convert(Double.class, number);
        //     look = Math.ceil(look * 10000);
        // }
        // Integer result = Convert.convert(Integer.class, look + (read.contains(".") ? (Math.random() * 1000) : (Math.random() * 10000)));
        // System.out.println("浏览量：" + result);


        // Post p = new Post();
        // p.setFromUrl("https://csdnnews.blog.csdn.net/article/details/130518065");
        // List<Post> postList = Arrays.asList(p);
        // ChromeOptions options = new ChromeOptions();
        // options.setPageLoadStrategy(PageLoadStrategy.EAGER);
        // ChromeDriver driver = new ChromeDriver(options);
        // SimpleDateFormat timeFormat = new SimpleDateFormat("yyyy-MM-dd");
        // for (Post post : postList) {
        //     driver.get(post.getFromUrl());
        //
        //     WebElement bar = driver.findElement(By.cssSelector(".article-info-box"));
        //     WebElement detail = driver.findElement(By.cssSelector("#content_views"));
        //     String[] split = bar.getText().split("\n");
        //     int i = split[0].equals("置顶") ? 1 : 0;
        //     String author = split[i];
        //     Date time = timeFormat.parse(split[1 + i].substring(2, 21));
        //     int looks = Convert.convert(Integer.class, split[2 + i]);
        //     int collects = Convert.convert(Integer.class, split[3 + i].substring(3));
        //     String tags = split[4+i].substring(split[4+i].indexOf("文章标签： ")+6);
        //     String content = detail.getAttribute("innerHTML");
        //
        //     System.out.println("author = " + author);
        //     System.out.println("time = " + time);
        //     System.out.println("looks = " + looks);
        //     System.out.println("collects = " + collects);
        //     System.out.println("tags = " + tags);
        //     System.out.println("content = " + content);
        //
        //     post.setAuthor(author);
        //     post.setCreateTime(time);
        //     post.setUpdateTime(time);
        //     post.setLooks(looks);
        //     // post.setCollects(collects);
        //     post.setCollects(0);
        //     post.setTags(tags);
        //     post.setContent(content);
        //
        //     post.setCreateBy("Admin");
        //     post.setRemark("从CSDN爬取的数据");
        // }
        // driver.quit();
    }
}
